﻿dynamic class loading.LoadProcessManage{
	
	public static var say:Function;
	
	private var n:Number;
	private var EventObjs:Object;
	private var myname:String;
	private var interId:Number;
	private var loadtrackObj:Array;
	private var $fps:Number;
	private var afterLoaded:Object;
	private var _afterloadedF:Function;
	
	
	//=================================================================
	/**
	* 监控频率
	* @return
	*/
	public function get Fps():Number{
		return this.$fps;
	}
	/**
	* 监控频率
	* @param	values
	*/
	public function set Fps(values:Number){
		this.$fps=values;
	}
	//=====================================================================
	
	/**
	* 加载监控初始化
	* @param	name 
	*/
	public function LoadProcessManage(name:String){
		if(name!="" && name !=undefined){
			this.myname=name;
		}else{
			this.myname="noName";
		}
		init();
		Say("初始化完成.");
	}
	private function init(){
		this.$fps=600;
		n=0;
		interId=-1;
		loadtrackObj=new Array();
		EventObjs=new Object();
	}
	/**
	* 增加事件监听
	* @param	eventName 事件
	* @param	eventObj  事件函数
	*/
	public function addEventListener(eventName:String,eventObj:Object){
		if(eventName=="" || eventName==undefined){
			this.Say("事件名不能为空!");
			return;
		}
		if(eventObj == undefined){
			this.Say("["+eventName+"]事件没有定义");
			return;
		}
		if(EventObjs[eventName]==undefined){
			EventObjs[eventName]=new Object();
		}
		EventObjs[eventName][n.toString()]=eventObj;
		eventObj.___id=n++;
	}
	/**
	* 去掉事件监听
	* @param	eventObj 事件函数
	*/
	public function removeEventListener(eventObj){
		trace(eventObj.___id);
		if(eventObj.___id==undefined) return ;
		for(var i:String in EventObjs){
			for(var l:String in EventObjs[i]){
				if(EventObjs[i][l].___id==eventObj.___id){
					delete EventObjs[i][l].___id;
					delete EventObjs[i][l];
					return;
				}
			}
		}
	}
	
	/**
	* 开始监控
	* @param	LoadTags 监控对像列表
	* @param	then 完成加载后的动作，或要求
	*/
	public function StartLoadTrack(LoadTags:Array,then:Object){
		if(this.interId<0){
			for(var i in LoadTags){
				var obj:Object={obj:LoadTags[i],p:-1,tt:0,ld:-1};
				this.loadtrackObj.push(obj);
			}
			this.afterLoaded=then;
			this.interId=setInterval(this.loadingTrack,this.$fps,this);
		}else{
			Say("加载监视中，不能监控新的加载...");
		}
	}
	
	private function loadingTrack(me:LoadProcessManage){
		var loaded:Boolean=true;
		var progressEP:Boolean=false;
		
		for(var i in me.loadtrackObj){
			var tag:Object=me.loadtrackObj[i].obj;
			var oldP:Number=me.loadtrackObj[i].ld;
			var type:String=typeof(tag);
			
			if(type=="object"){
				type=me.getTypeDetail(me.loadtrackObj[i].obj);
			}
			switch(type){
				case "movieclip":
					var mc=tag; 
					//trace(mc+"==="+me.loadtrackObj[i].tt);
					if(me.loadtrackObj[i].tt!=-2){
						var ttt=mc.getBytesTotal();
						
						if(me.loadtrackObj[i].tt==0 || me.loadtrackObj[i].tt==-1){
							me.loadtrackObj[i].tt=ttt;
							if(me.loadtrackObj[i].tt==-1 || mc==null){
								me.loadtrackObj[i].tt=-3;
								loaded=false;
								break;
							}
						}
						if(me.loadtrackObj[i].tt<-2 && ttt==-1){
							me.loadtrackObj[i].tt--;
							if(me.loadtrackObj[i].tt<-20){
								loaded=true;
								me.loadtrackObj[i].tt=-2;
								me.PEvents("error","mc加载出错["+mc+"].",tag);
								break;
							}else{
								loaded=false;
								break;
							}
						}else{
							me.loadtrackObj[i].tt=ttt;
							//trace("set ttt="+ttt+"  & lll="+mc.getBytesLoaded());
						}
						//trace(me.loadtrackObj[i].tt+"||"+me.loadtrackObj[i].ld);
						var ld:Number=mc.getBytesLoaded();
						if(oldP!=ld){
							me.loadtrackObj[i].ld=ld;
							progressEP=true;
							me.loadtrackObj[i].p=(int(10000*ld/me.loadtrackObj[i].tt))/100;
						}
						if(me.loadtrackObj[i].ld!=me.loadtrackObj[i].tt){
							loaded=false;
						}
					}
				break;
				
				case "sound":
					var sound:Sound=Sound(tag);
					if(me.loadtrackObj[i].tt!=-2){
						if(me.loadtrackObj[i].tt==0 || me.loadtrackObj[i].tt==-1){
							me.loadtrackObj[i].tt=sound.getBytesTotal();
							if(me.loadtrackObj[i].tt==undefined){
								me.PEvents("error","sound加载出错["+sound+"].",tag);
								me.loadtrackObj[i].tt=-2;
								break;
							}
							if(me.loadtrackObj[i].tt==0 || me.loadtrackObj[i].tt==-1){
								loaded=false;
								break;
							}
						}
						var ld:Number=sound.getBytesLoaded();
						if(oldP!=ld){
							me.loadtrackObj[i].ld=ld;
							progressEP=true;
							me.loadtrackObj[i].p=(int(10000*ld/me.loadtrackObj[i].tt))/100;
						}
						if(me.loadtrackObj[i].ld!=me.loadtrackObj[i].tt){
							loaded=false;
						}
					}
				break;
				
				case "loadvars":
					var loadvars:LoadVars=LoadVars(tag);
					if(me.loadtrackObj[i].tt!=-2){
						var tt:Number=loadvars.getBytesTotal();
						var ld:Number=loadvars.getBytesLoaded();
						//trace(tt+" ::::  "+ld);
						if(tt==undefined){
							if(tag["tag"]==undefined){
								tag.tag=me;
								tag.__id=i
								loadvars.onHTTPStatus=me.OnHTTPStatus;
								loadvars.onLoad=me.OnLoadF;
							}
							loaded=false;
						}else{
							me.loadtrackObj[i].tt=tt;
							if(oldP!=ld){
								me.loadtrackObj[i].ld=ld;
								progressEP=true;
								me.loadtrackObj[i].p=(int(10000*ld/me.loadtrackObj[i].tt))/100;
							}
							if(me.loadtrackObj[i].ld!=me.loadtrackObj[i].tt){
								loaded=false;
							}
						}
					}
				break;
				
				case "xml":
					var xml=XML(tag);
					if(me.loadtrackObj[i].tt!=-2){
						var tt:Number=xml.getBytesTotal();
						var ld:Number=xml.getBytesLoaded();
						if(tt==undefined){
							if(tag["tag"]==undefined){
								tag.tag=me;
								tag.__id=i
								xml.onHTTPStatus=me.OnHTTPStatus;
								xml.onLoad=me.OnLoadF;
							}
							loaded=false;
						}else{
							me.loadtrackObj[i].tt=tt;
							if(oldP!=ld){
								me.loadtrackObj[i].ld=ld;
								progressEP=true;
								me.loadtrackObj[i].p=(int(10000*ld/me.loadtrackObj[i].tt))/100;
							}
							if(me.loadtrackObj[i].ld!=me.loadtrackObj[i].tt){
								loaded=false;
							}
						}
					}
				break;
				
				
				default:
				if(oldP!=-2){
					me.loadtrackObj[i].ld=-2;
					me.PEvents("error","不能检测的加载对像["+type+"].",tag);
				}
				break;
			}
			
		}
		if(progressEP){
			var objs:Object=new Object();
			objs.general=me.getTTprogress();
			objs.detail=me.loadtrackObj;
			me.PEvents("progress","all progress...",objs);
		}
		if(loaded){
			me.AfterLoaded();
		}
	}
	
	private function OnHTTPStatus(n:Number){
		this["errorid"]=n;
		if(n<100){
			if(this["tag"].loadtrackObj[this["__id"]].tt!=-2){ 
				this["tag"].loadtrackObj[this["__id"]].tt=-2;
				this["tag"].PEvents("error","发生flashplayer通讯错误:[errorid:: "+n+"]",this);
				delete this["tag"];
				delete this["__id"];
			}
		}
		else if(n==200){
		}else if(n>200){
			if(this["tag"].loadtrackObj[this["__id"]].tt!=-2){ 
				this["tag"].loadtrackObj[this["__id"]].tt=-2;
				this["tag"].PEvents("error","加载中发生http错误["+HTTP_CODE.GetMsg(n)+"][errorid:: "+n+"]",this);
				delete this["tag"];
				delete this["__id"];
			}
		}
		
	}
	private function OnLoadF(success){
		if(!success){
			if(this["tag"].loadtrackObj[this["__id"]].tt!=-2){
				this["tag"].loadtrackObj[this["__id"]].tt=-2;
				this["tag"].PEvents("error","加载中发生错误.",this);
				delete this["tag"];
				delete this["__id"];
			}
		}
		
	}
	private function getTTprogress():Object{
		var obj:Object=new Object();
		var tt:Number=0;
		var ld:Number=0;
		for(var i in this.loadtrackObj){
			if(this.loadtrackObj[i].tt>0){
				tt+=this.loadtrackObj[i].tt;
				ld+=this.loadtrackObj[i].ld;
			}
		}
		var p:Number=(int(10000*ld/tt))/100;
		obj.percent=p;
		obj.total=tt;
		obj.loaded=ld;
		return obj;
	}
	private function AfterLoaded(){
		var LTO:Object=this.loadtrackObj;
		clearInterval(this.interId);
		if(this.afterLoaded!=undefined){
			if(typeof(this.afterLoaded)=="function"){
				this._afterloadedF=Function(this.afterLoaded);
			}
			if(typeof(this.afterLoaded)=="movieclip"){
				this.afterLoaded.play();
			}
		}
		this.afterLoaded=new Object();
		this.interId=-1;
		this.PEvents("loaded","load ok!",LTO);
		if(this._afterloadedF!=undefined){
			this._afterloadedF(LTO);
		}
		this._afterloadedF=null;
		//this.RemoveAllListener();
		//this.loadtrackObj=new Array();
	}
	public function RemoveAllListener(){
		var a:Array=new Array();
		for(var i in this.loadtrackObj){
			for(var l in this.loadtrackObj[i]){
				a.push(this.loadtrackObj[i][l]);
			}
		}
		for(var i in a){
			this.removeEventListener(a);
		}
	}
	/**
	* 事件广播
	* @param	eventName 事件名
	* @param	msg		  事件消息
	* @param	args	  事件附带数据
	*/
	private function PEvents(eventName:String,msg:String,args:Object){
		if(this.EventObjs[eventName]==undefined) return;
		var obj:Object=this.EventObjs[eventName];
		for(var i in obj){
			obj[i][eventName](msg,args);
		}
	}
	private function getTypeDetail(obj:Object):String{
		if(obj==undefined) return "null";
		var soundif:Sound=Sound(obj);
		var loadvarif:LoadVars=LoadVars(obj);
		var netstreamif:NetStream=NetStream(obj);
		var xmlif:XML=XML(obj);
		
		if(soundif!=null && loadvarif==null && netstreamif==null && xmlif==null) return "sound";
		if(soundif==null && loadvarif!=null && netstreamif==null && xmlif==null) return "loadvars";
		if(soundif==null && loadvarif==null && netstreamif!=null && xmlif==null) return "netstream";
		if(soundif==null && loadvarif==null && netstreamif==null && xmlif!=null) return "xml";
		
		Debug.traceAllObj(obj);
		return "object";
	}
	private function Say(o:Object){
		say("LPM["+myname+"]:"+o);
	}
	/**
	* 帮助
	*/
	public static function HELP(){
		var st:String="\r";
		st+="--------- 加载监控帮助 -----\r";
		st+="copyright Tophy 2006/7/4\r";
		st+="version  2.0\r";
		st+="----------------------------\r";
		st+="静态函数及属性部分：\r";
		st+="---------------------\r";
		st+="say:Function \r";
		st+="原型  say(obj:Object)\r";
		st+="用于输出调试消息的接口\r";
		st+="\r";
		st+="\r";
		st+="\r";
		st+="实例方法及属性：\r";
		st+="---------------------\r";
		st+="Fps:Number\r";
		st+="用于设置或获取加载监控频率\r";
		st+="\r";
		st+="new LoadProcessManage(name:String)\r";
		st+="构造函数 name为加载标识\r";
		st+="\r";
		st+="实例.StartLoadTrack(LoadTags:Array,then:Object)\r";
		st+="创建一个加载监控\r";
		st+="loadTages为被监控的目标。可以是 MovieClip,Sound,LoadVers,XML \r";
		st+="then为加载完成后的后续动作。可以是function(执行，参数为LoadTags)，可以是MovieClip(play)\r，可以是null\r";
		st+="\r";
		st+="addEventListener(eventName:String,eventObj:Object)\r";
		st+="增加一个事件，其中\r";
		st+="eventName为事件名，可以是\"error\",\"loaded\",\"progress\"\r";
		st+="eventObj中应该有需要注册的事件名对应的函数，该函数应该有2个参数。一个为相关消息string，一个为参数:object\r";
		st+="事件说明：\r";
		st+="1、注册事件\r";
		st+="var eObj:Object=new Object();\r";
		st+="eObj.error=function(msg:String,args:Obj);\r";
		st+="LPM实例.addEventListener(\"error\",eObj);\r";
		st+="\r";
		st+="2、各事件函数说明\r";
		st+="error:\r";
		st+="	msg: 错误消息\r";
		st+="	args: 出错的加载监控对像\r";
		st+="\r";
		st+="loaded:\r";
		st+="	msg: 加载完成消息\r";
		st+="	args: *加载对象结构数组\r";
		st+="\r";
		st+="progress:\r";
		st+="	msg: 加载进度消息\r";
		st+="	args: **加载进度结构对象\r";
		st+="\r";
		st+="说明： \r";
		st+="*加载对象结构数组\r";
		st+="一个数组，数组元素为以下结构\r";
		st+="obj.obj=加载对象\r";
		st+="obj.p=加载进度(百分比)\r";
		st+="obj.ld=已经加载的字节数\r";
		st+="obj.tt=总字节数\r";
		st+="\r";
		st+="\r";
		st+="**加载进度结构对象\r";
		st+="一个Object数据结构如下\r";
		st+="obj.general.percent=总体加载进度\r";
		st+="obj.general.total=总体加载数据字节数\r";
		st+="obj.general.loaded=总体已经加载的数据字节数\r";
		st+="obj.detail = 加载对象结构数组\r";
		st+="\r";
		st+="\r";
		st+="\r";
		st+="delEventListener(eventObj:Object)\r";
		st+="删除事件注册\r";
		st+="注意：完成加载后，自动删除事件注册\r";
		st+="-----------------------------------\r";
		say(st);
	}
}